#!/bin/bash -e

FAN_STATUS_UNKNOWN="Unknown"
FAN_STATUS_NORMAL="Normal"
FAN_STATUS_ABNORMAL="Abnormal"

create_log()
{
    local service="xyz.openbmc_project.Logging"
    local object_path="/xyz/openbmc_project/logging"
    local interface="xyz.openbmc_project.Logging.Create"
    local message="Fan status abnormal"
    local severity="xyz.openbmc_project.Logging.Entry.Level.Error"
    local arg="CALLOUT_INVENTORY_PATH"
    local value="/xyz/openbmc_project/inventory/fan"

    busctl call "$service" "$object_path" "$interface" Create "ssa{ss}" "$message" "$severity" 1 "$arg" "$value"
}

resolve_log()
{
    local service="xyz.openbmc_project.ObjectMapper"
    local object_path="/xyz/openbmc_project/inventory/fan/fault"
    local interface="xyz.openbmc_project.Association"
    local property="endpoints"

    mapfile -t -d " " endpoint_array < <(busctl get-property "$service" "$object_path" "$interface" "$property" | tr -d '"\n')

    for ((i = 2; i < ${#endpoint_array[@]}; i++)); do
        endpoint="${endpoint_array[$i]}"
        busctl set-property xyz.openbmc_project.Logging "$endpoint" xyz.openbmc_project.Logging.Entry Resolved b true
    done
}

check_fcb_fan_status()
{
    local fcb_num=$1

    if ! [[ $fcb_num =~ ^[0-5]$ ]]; then
        echo "$FAN_STATUS_UNKNOWN"
        return 1
    fi

    local service="xyz.openbmc_project.FanSensor"
    local interface="xyz.openbmc_project.Sensor.Threshold.Critical"
    local property_list=("CriticalAlarmHigh" "CriticalAlarmLow")
    local fan_name_prefix=("FCB_BOT_0" "FCB_BOT_1" "FCB_MID_0" "FCB_MID_1" "FCB_TOP_0" "FCB_TOP_1")
    local in_out=("IL" "OL")

    for index in {0..7}
    do
        local object_path="/xyz/openbmc_project/sensors/fan_tach/${fan_name_prefix[$fcb_num]}_FAN$((index / 2))_TACH_${in_out[$((index % 2))]}_SPEED_RPM"
        for property in "${property_list[@]}"; do
            tach_alarm=$(busctl get-property "$service" "$object_path" "$interface" "$property" | cut -d ' ' -f2)
            if [ "$tach_alarm" = "true" ]; then
                echo "$FAN_STATUS_ABNORMAL"
                return 0
            fi
        done
    done

    echo "$FAN_STATUS_NORMAL"
    return 0
}

pre_status=$FAN_STATUS_UNKNOWN

while true
do
    fan_status=$FAN_STATUS_NORMAL
    # Get the FCBs' presence status from the CMM CPLD
    fcb_prsnt_reg=$(i2cget -f -y 0x00 0x15 0x01)

    for i in {0..5}
    do
        # Check the presence of each FCB
        if (( (fcb_prsnt_reg & (1 << i)) != 0 )); then
            fan_status=$FAN_STATUS_ABNORMAL
            break
        else
            # Check each sensor on the FCB whether alert critical alarm
            fan_status=$(check_fcb_fan_status "$i")
            if [ "$fan_status" = "$FAN_STATUS_ABNORMAL" ]; then
                break
            fi
        fi
    done

    if [ "$fan_status" = "$FAN_STATUS_ABNORMAL" ] && [ "$pre_status" != "$FAN_STATUS_ABNORMAL" ]; then
        create_log
        pre_status="$FAN_STATUS_ABNORMAL"
    elif [ "$fan_status" = "$FAN_STATUS_NORMAL" ] && [ "$pre_status" != "$FAN_STATUS_NORMAL" ]; then
        resolve_log
        pre_status="$FAN_STATUS_NORMAL"
    fi
    sleep 1
done
